﻿using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using élénkPróbája.extentions;
using élénkPróbája.Test.dto;
using élénkPróbája.Test.extention;
using élénkPróbája.validators;

namespace élénkPróbája.Test
{
    [TestClass]
    public class ExceedOrEqualValidatorTester
    {
        private TestValidator validator;
        private const int value = 1; 
        public ExceedOrEqualValidatorTester()
        {
            CultureScope.SetDefaultCulture();
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(value));
        }

        [TestMethod]
        public void Should_fail_when_less_than_input()
        {
            var result = validator.Validate(new Company() { Id = 0 });
            result.IsValid.ShouldBeFalse();
        }

        [TestMethod]
        public void Should_succeed_when_greater_than_input()
        {
            var result = validator.Validate(new Company { Id = 2 });
            result.IsValid.ShouldBeTrue();
        }

        [TestMethod]
        public void Should_succeed_when_equal_to_input()
        {
            var result = validator.Validate(new Company { Id = value });
            result.IsValid.ShouldBeTrue();
        }

        [TestMethod]
        public void Should_set_default_error_when_validation_fails()
        {
            var result = validator.Validate(new Company { Id = 0 });
            result.Errors.Single().ErrorMessage.ShouldEqual("'' must be greater than or equal to '1'.");
        }

        [TestMethod]
        public void Validates_with_property()
        {
            var validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(1));
            var result = validator.Validate(new Company { Id = 0 });
            result.IsValid.ShouldBeFalse();
        }

        [TestMethod]
        public void Validates_with_nullable_property()
        {
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(1));

            var resultNull = validator.Validate(new Company { Id = 0 });
            var resultLess = validator.Validate(new Company { Id = -1 });
            var resultEqual = validator.Validate(new Company { Id = 1 });
            var resultMore = validator.Validate(new Company { Id = 2 });

            resultNull.IsValid.ShouldBeFalse();
            resultLess.IsValid.ShouldBeFalse();
            resultEqual.IsValid.ShouldBeTrue();
            resultMore.IsValid.ShouldBeTrue();
        }

        [TestMethod]
        public void Comparison_type()
        {
            var propertyValidator = validator.CreateDescriptor()
                .GetValidatorsForMember("Id").Cast<ExceedOrEqualValidator>().Single();

            propertyValidator.Comparison.ShouldEqual(Comparison.GreaterThanOrEqual);
        }

        [TestMethod]
        public void Validates_with_nullable_when_property_is_null()
        {
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(5));
            var result = validator.Validate(new Company());
            result.IsValid.ShouldBeFalse();
        }

        [TestMethod]
        public void Validates_with_nullable_when_property_not_null()
        {
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(5));
            var result = validator.Validate(new Company { Id = 1 });
            result.IsValid.ShouldBeFalse();
        }

        [TestMethod]
        public void Should_localize_value()
        {
            using (new CultureScope("fr-fr"))
            {
                var orderValidator = new InlineValidator<Account>();
                orderValidator.RuleFor(x => x.Balance).GreaterThanOrEqualTo(1.2M).WithMessage("{ComparisonValue}");
                var result = orderValidator.Validate(new Account());
                var msg = result.Errors[0].ErrorMessage;
                msg.ShouldEqual("1,2");
            }
        }

        [TestMethod]
        public void Validates_with_nullable_when_property_is_null_cross_property()
        {
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(x => x.Id));
            var result = validator.Validate(new Company { Id = 5 });
            result.IsValid.ShouldBeTrue();
        }

        [TestMethod]
        public void Validates_with_nullable_when_property_not_null_cross_property()
        {
            validator = new TestValidator(v => v.RuleFor(x => x.Id).GreaterThanOrEqualTo(x => x.Id));
            var result = validator.Validate(new Company { Id = 5 });
            result.IsValid.ShouldBeTrue();
        }
    }
}
